function delay(ms) {
	return new Promise((resovle) => setTimeout(resovle, ms))
}

delay(3000).then(() => console.log('runs after 3 seconds'))

// * 这段代码的执行过程可以分为几个关键步骤，以下是详细的解析：

// * 执行过程

// * 【同步执行 delay 函数】：
// * 当调用 delay(3000) 函数时，它会同步执行。
// * 在这个函数内部，会创建一个新的 Promise 对象，并立即调用执行器函数（executor function），其中包含 setTimeout。这会创建一个状态为“待定”（pending）的 Promise 对象。
// * setTimeout(resovle, ms) 会在3000毫秒后调度一个回调来解析这个 Promise，但这个回调并不会立即执行，而是被放入宏任务队列中等待执行。

// * 【完成同步代码】：
// * 调用 delay 后，任何后续的同步代码都会执行。在这个例子中，delay 调用后没有其他同步代码。

// * 【微任务执行】：
// * 一旦所有同步代码执行完毕，JavaScript 引擎会开始执行微任务队列中的任务。在这种情况下，由于 .then() 是在 Promise 被解析后才会被调用，因此它会在 Promise 完成后被添加到微任务队列中。

// * 【宏任务执行】：
// * 经过3000毫秒后，setTimeout 中的回调函数会被放入宏任务队列中。
// * 此时，宏任务队列中的任务会被逐一执行，包括之前设置的 resolve 函数。这会将 Promise 状态从“待定”变为“已解决”（fulfilled），并触发.then() 中的回调。

// * 【总结】
// * 因此，您提到的顺序是正确的：首先是同步任务，然后是微任务（即 .then() 的回调），最后是宏任务（即 setTimeout 的回调）。
// * 虽然.then() 是微任务，但它是在 setTimeout 的延时任务完成后才会被执行，因为它依赖于 Promise 的解析。
// * 这样看起来像是微任务在延时任务之后执行，但实际上是因为它们之间有依赖关系。
